package com.deparse.dpframe.ui.activity;

import android.annotation.TargetApi;
import android.app.ActivityManager;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v7.app.AppCompatActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.RelativeLayout;
import android.widget.Toast;

import com.deparse.dpframe.bean.DPView;
import com.deparse.dpframe.common.DPConsts;
import com.deparse.dpframe.common.DPBusEvent;
import com.deparse.dpframe.common.DPBusEventCommands;
import com.deparse.dpframe.libs.SystemBarTintManager;
import com.deparse.dpframe.utils.DPLogUtil;

import org.simple.eventbus.EventBus;

import java.lang.reflect.Field;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by MartinDKent on 2016/1/16.
 */
public class DPBaseActivity extends AppCompatActivity {

    private Map<Integer, DPView> DPViewCacher = new HashMap<>(20);
    private Map<Integer, View> viewCacher = new HashMap<>(20);

    private LayoutInflater inflater;
    private boolean onCreateExecuted = false;
    private boolean isAppBackground;

    private Map<Integer, Integer> requestCodes = new HashMap<>();
    private boolean isJugingBackground = false;

    private FragmentManager fragmentManager = null;

    private RelativeLayout baseLayout;

    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            DPBaseActivity.this.handleMessage(msg);
        }
    };

    /**
     * handleMessage
     *
     * @param msg
     */
    protected void handleMessage(Message msg) {

    }

    /**
     * sendEmptyMessage
     *
     * @param what
     */
    protected void sendEmptyMessage(int what) {
        handler.sendEmptyMessage(what);
    }

    /**
     * sendEmptyMessageDelayed
     *
     * @param what
     * @param delay
     */
    protected void sendEmptyMessageDelayed(int what, long delay) {
        handler.sendEmptyMessageDelayed(what, delay);
    }

    /**
     * sendMessage
     *
     * @param msg
     */
    protected void sendMessage(Message msg) {
        handler.sendMessage(msg);
    }

    /**
     * sendMessageDelayed
     *
     * @param msg
     * @param delay
     */
    protected void sendMessageDelayed(Message msg, long delay) {
        handler.sendMessageDelayed(msg, delay);
    }

    /**
     * removeMessage
     *
     * @param waht
     */
    protected void removeMessage(int waht) {
        handler.removeMessages(waht);
    }

    /**
     * post
     *
     * @param runnable
     */
    public void post(Runnable runnable) {
        handler.post(runnable);
    }

    /**
     * postDelayed
     *
     * @param runnable
     * @param delayMillis
     */
    public void postDelayed(Runnable runnable, long delayMillis) {
        handler.postDelayed(runnable, delayMillis);
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        EventBus.getDefault().register(this);

        baseLayout = new RelativeLayout(this);
        baseLayout.setFitsSystemWindows(true);
        baseLayout.setClipToPadding(true);
        baseLayout.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
        super.setContentView(baseLayout);

        inflater = getLayoutInflater();
        onCreateExecuted = true;
        fragmentManager = getSupportFragmentManager();
    }

    private SystemBarTintManager tintManager;

    /**
     * setStausBarBackgroundColor
     *
     * @param color
     */
    @TargetApi(19)
    protected void setStausBarBackgroundColor(int color) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
            tintManager = new SystemBarTintManager(this);
            tintManager.setStatusBarTintColor(color);
            tintManager.setStatusBarTintEnabled(true);
        }
    }

    /**
     * onEventMainThread
     *
     * @param DPBusEvent
     */
    public void onEventMainThread(DPBusEvent DPBusEvent) {
        if (null != DPBusEvent && DPBusEventCommands.EVENT_FINISH_ACTIVITY == DPBusEvent.what) {
            finish();
        } else {
            onBusEventReceived(DPBusEvent);
        }
    }

    /**
     * onBusEventReceived
     *
     * @param DPBusEvent
     */
    private void onBusEventReceived(DPBusEvent DPBusEvent) {

    }

    /**
     * postBusEvent
     *
     * @param DPBusEvent
     */
    public void postBusEvent(DPBusEvent DPBusEvent) {
        EventBus.getDefault().post(DPBusEvent);
    }

    /**
     * postBusEventDelayed
     *
     * @param DPBusEvent
     * @param duration
     */
    public void postBusEventDelayed(final DPBusEvent DPBusEvent, final int duration) {
        postDelayed(new Runnable() {
            @Override
            public void run() {
                postBusEvent(DPBusEvent);
            }
        }, duration);
    }

    /**
     * finishAllActivities
     */
    protected void finishAllActivities() {
        DPBusEvent DPBusEvent = new DPBusEvent();
        DPBusEvent.what = DPBusEventCommands.EVENT_FINISH_ACTIVITY;
        postBusEvent(DPBusEvent);
    }

    /**
     * setContentView
     *
     * @param layoutResID
     */
    @Override
    public void setContentView(int layoutResID) {
        baseLayout.removeAllViewsInLayout();
        baseLayout.addView(inflate(layoutResID), new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
    }

    /**
     * setContentView
     *
     * @param view
     */
    @Override
    public void setContentView(View view) {
        baseLayout.removeAllViewsInLayout();
        baseLayout.addView(view, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
    }

    /**
     * setContentView
     *
     * @param view
     * @param params
     */
    @Override
    public void setContentView(View view, ViewGroup.LayoutParams params) {
        baseLayout.removeAllViewsInLayout();
        baseLayout.addView(view, params);
    }

    /**
     * addContentView
     *
     * @param view
     * @param params
     */
    @Override
    public void addContentView(View view, ViewGroup.LayoutParams params) {
        baseLayout.addView(view, params);
    }

    /**
     * addContentView
     *
     * @param view
     * @param index
     * @param params
     */
    public void addContentView(View view, int index, ViewGroup.LayoutParams params) {
        baseLayout.addView(view, index, params);
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (onCreateExecuted) {
            onFirstResume();
        } else {
            onAnotherResume();
        }
    }

    /**
     * onFirstResume
     */
    protected void onFirstResume() {

    }

    /**
     * onAnotherResume
     */
    protected void onAnotherResume() {
        AsyncTask task = new AsyncTask() {
            @Override
            protected Object doInBackground(Object[] params) {
                while (isJugingBackground()) {
                    try {
                        Thread.sleep(50);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                return null;
            }

            @Override
            protected void onPostExecute(Object o) {
                super.onPostExecute(o);
                if (isAppBackground()) {
                    setIsAppBackground(false);
                    onReturnFromOtherApp();
                } else {
                    onReturnFromSelf();
                }
            }
        };
        task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
    }

    /**
     * onReturnFromSelf
     */
    protected void onReturnFromSelf() {

    }

    /**
     * onReturnFromOtherApp
     */
    protected void onReturnFromOtherApp() {

    }

    /**
     * onStop
     */
    @Override
    protected void onStop() {
        super.onStop();
        onCreateExecuted = false;

        AsyncTask task = new AsyncTask() {
            @Override
            protected void onPreExecute() {
                super.onPreExecute();
                setIsJugingBackground(true);
            }

            @Override
            protected Object doInBackground(Object[] params) {
                return jugeBackground();
            }

            @Override
            protected void onPostExecute(Object o) {
                super.onPostExecute(o);
                setIsAppBackground((boolean) o);
                setIsJugingBackground(false);
            }
        };
        task.execute();
    }

    /**
     * onDestroy
     */
    @Override
    protected void onDestroy() {
        EventBus.getDefault().unregister(this);
        super.onDestroy();
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
//        super.onSaveInstanceState(outState);
    }

    /**
     * isJugingBackground
     *
     * @return
     */
    private boolean isJugingBackground() {
        return isJugingBackground;
    }

    /**
     * setIsJugingBackground
     *
     * @param isJuging
     */
    private void setIsJugingBackground(boolean isJuging) {
        this.isJugingBackground = isJuging;
    }

    /**
     * setIsAppBackground
     *
     * @param isAppBackground
     */
    private void setIsAppBackground(boolean isAppBackground) {
        this.isAppBackground = isAppBackground;
    }

    /**
     * isAppBackground
     *
     * @return
     */
    private boolean isAppBackground() {
        return isAppBackground;
    }

    /**
     * jugeBackground
     *
     * @return
     */
    private boolean jugeBackground() {
        ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
        List<ActivityManager.RunningAppProcessInfo> appProcesses = activityManager.getRunningAppProcesses();
        if (null == appProcesses) {
            return false;
        }
        for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) {
            if (appProcess.processName.equals(getPackageName())) {
                if (appProcess.importance != ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
                    DPLogUtil.d("后台" + appProcess.processName);
                    return true;
                } else {
                    DPLogUtil.d("前台" + appProcess.processName);
                    return false;
                }
            }
        }
        return false;
    }

    /**
     * getContentView
     *
     * @return
     */
    public View getContentView() {
        return baseLayout;
    }

    /**
     * inflate
     *
     * @param layoutResId
     * @return
     */
    public View inflate(int layoutResId) {
        return inflater.inflate(layoutResId, null);
    }

    /**
     * F
     *
     * @param resId
     * @param <T>
     * @return
     */
    public <T extends View> T F(int resId) {
        View view;
        if (null == viewCacher.get(resId)) {
            view = F(getContentView(), resId);
        } else {
            view = viewCacher.get(resId);
        }
        return (T) view;
    }

    /**
     * F
     *
     * @param view
     * @param resId
     * @param <T>
     * @return
     */
    public <T extends View> T F(View view, int resId) {
        return null == view ? null : (T) view.findViewById(resId);
    }

    /**
     * $
     *
     * @param resId
     * @return
     */
    protected DPView $(int resId) {
        if (null == DPViewCacher.get(resId)) {
            DPViewCacher.put(resId, new DPView(F(resId)));
        }
        return DPViewCacher.get(resId);
    }

    /**
     * fromLayout
     *
     * @param layoutResId
     * @return
     */
    protected DPView fromLayout(int layoutResId) {
        if (null == DPViewCacher.get(layoutResId)) {
            DPViewCacher.put(layoutResId, new DPView(getLayoutInflater().inflate(layoutResId, null)));
        }
        return DPViewCacher.get(layoutResId);
    }

    /**
     * getRequestCode
     *
     * @param key
     * @return
     */
    public int getRequestCode(Integer key) {
        int requestCode;
        if (requestCodes.containsKey(key)) {
            requestCode = requestCodes.get(key);
        } else {
            requestCode = Long.valueOf(new Date().getTime()).intValue();
            requestCodes.put(key, requestCode);
        }
        return requestCode;
    }

    /**
     * startActivity
     *
     * @param cls
     * @param extras
     */
    public void startActivity(Class<?> cls, String... extras) {
        Intent intent = new Intent(this, cls);
        intent.putExtra(DPConsts.ACTIVITY_START_STRING_EXTRAS, extras);
        super.startActivity(intent);
    }

    /**
     * startActivityForResult
     *
     * @param cls
     * @param requestCode
     * @param data
     */
    public void startActivityForResult(Class<?> cls, int requestCode, String... data) {
        Intent intent = new Intent(this, cls);
        intent.putExtra(DPConsts.ACTIVITY_START_STRING_EXTRAS, data);
        super.startActivityForResult(intent, requestCode);
    }

    /**
     * finish
     *
     * @param resultCode
     * @param data
     */
    public void finish(int resultCode, String... data) {
        Intent intent = new Intent();
        intent.putExtra(DPConsts.ACTIVITY_RESULT_STRING_EXTRAS, data);
        setResult(resultCode, intent);
        super.finish();
    }

    /**
     * startActivityWithTaskCleared
     *
     * @param cls
     * @param extras
     */
    public void startActivityWithTaskCleared(Class<?> cls, String... extras) {
        finishAllActivities();
        Intent intent = new Intent(this, cls);
        intent.putExtra(DPConsts.ACTIVITY_START_STRING_EXTRAS, extras);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        super.startActivity(intent);
    }

    /**
     * onActivityResult
     *
     * @param requestCode
     * @param resultCode
     * @param data
     */
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        List<Fragment> fragments = getSupportFragmentManager().getFragments();
        if (null != fragments) {
            for (Fragment fragment : fragments) {
                if (null == fragment) {
                    continue;
                }
                fragment.onActivityResult(requestCode, resultCode, data);
            }
        }
        if (null != data && data.hasExtra(DPConsts.ACTIVITY_RESULT_STRING_EXTRAS)) {
            onActivityResult(requestCode, resultCode, data.getStringArrayExtra(DPConsts.ACTIVITY_RESULT_STRING_EXTRAS));
        } else {
            onActivityResult(requestCode, resultCode, (String[]) null);
        }
    }

    /**
     * onActivityResult
     *
     * @param requestCode
     * @param resultCode
     * @param data
     */
    protected void onActivityResult(int requestCode, int resultCode, String[] data) {

    }

    /**
     * getActivityStartExtra
     *
     * @return
     */
    public String[] getActivityStartExtra() {
        if (null == getIntent()) {
            return null;
        }
        return getIntent().getStringArrayExtra(DPConsts.ACTIVITY_START_STRING_EXTRAS);
    }

    /**
     * replaceFragment
     *
     * @param container
     * @param fragment
     * @param tag
     */
    protected void replaceFragment(int container, Fragment fragment, String... tag) {
        if (isEmpty(tag)) {
            fragmentManager.beginTransaction().replace(container, fragment).commit();
        } else {
            fragmentManager.beginTransaction().replace(container, fragment, tag[0]).commit();
        }
    }

    /**
     * replaceFragment
     *
     * @param container
     * @param fragment
     * @param animEnter
     * @param animExit
     * @param tag
     */
    protected void replaceFragment(int container, Fragment fragment, int animEnter, int animExit, String... tag) {
        if (isEmpty(tag)) {
            fragmentManager.beginTransaction().replace(container, fragment).setCustomAnimations(animEnter, animExit).commit();
        } else {
            fragmentManager.beginTransaction().replace(container, fragment, tag[0]).setCustomAnimations(animEnter, animExit).commit();
        }
    }

    /**
     * findFragmentByTag
     *
     * @param tag
     * @return
     */
    protected Fragment findFragmentByTag(String tag) {
        return fragmentManager.findFragmentByTag(tag);
    }

    /**
     * addFragment
     *
     * @param container
     * @param fragment
     * @param tag
     */
    protected void addFragment(int container, Fragment fragment, String... tag) {
        if (isEmpty(tag)) {
            fragmentManager.beginTransaction().add(container, fragment).commit();
        } else {
            fragmentManager.beginTransaction().add(container, fragment, tag[0]).commit();
        }
    }

    /**
     * addFragment
     *
     * @param container
     * @param id
     * @param fragment
     * @param tag
     */
    protected void addFragment(int container, int id, Fragment fragment, String... tag) {
        if (isEmpty(tag)) {
            fragmentManager.beginTransaction().add(container, fragment).commit();
        } else {
            fragmentManager.beginTransaction().add(container, fragment, tag[0]).commit();
        }
    }

    /**
     * showFragment
     *
     * @param fragment
     */
    protected void showFragment(Fragment fragment) {
        fragmentManager.beginTransaction().show(fragment).commit();
    }

    /**
     * hideFragment
     *
     * @param fragment
     */
    protected void hideFragment(Fragment fragment) {
        fragmentManager.beginTransaction().hide(fragment).commit();
    }

    /**
     * showFragment
     *
     * @param fragment
     * @param animEnter
     * @param animExit
     */
    protected void showFragment(Fragment fragment, int animEnter, int animExit) {
        fragmentManager.beginTransaction().show(fragment).setCustomAnimations(animEnter, animExit).commit();
    }

    /**
     * hideFragment
     *
     * @param fragment
     * @param animEnter
     * @param animExit
     */
    protected void hideFragment(Fragment fragment, int animEnter, int animExit) {
        fragmentManager.beginTransaction().hide(fragment).setCustomAnimations(animEnter, animExit).commit();
    }

    private Toast toast = null;

    /**
     * showToast
     *
     * @param resId
     * @param dependency
     */
    public void showToast(int resId, Boolean... dependency) {
        showToast(getString(resId), dependency);
    }

    /**
     * showToast
     *
     * @param msg
     * @param dependency
     */
    public void showToast(String msg, Boolean... dependency) {
        if (!isEmpty(dependency) && true == dependency[0]) {
            Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
        }
        if (null == toast) {
            toast = Toast.makeText(this, msg, Toast.LENGTH_SHORT);
        } else {
            toast.setText(msg);
        }
        toast.show();
    }

    /**
     * isEmpty
     *
     * @param src
     * @return
     */
    protected static boolean isEmpty(String src) {
        return null == src || "".equals(src);
    }

    /**
     * isEmpty
     *
     * @param src
     * @param <T>
     * @return
     */
    protected static <T> boolean isEmpty(T[] src) {
        return null == src || 0 == src.length;
    }

    /**
     * isEmpty
     *
     * @param src
     * @return
     */
    protected static boolean isEmpty(List<?> src) {
        return null == src || 0 == src.size();
    }

    /**
     * isEmpty
     *
     * @param src
     * @return
     */
    protected static boolean isEmpty(Map<?, ?> src) {
        return null == src || 0 == src.size();
    }
}
